/**
 * 
 */
package ganga.custodian;

import ganga.gps.LocationMonitor;
import ganga.sensors.AccelerometerMonitor;
import ganga.sportsman.Application;
import ganga.ui.StatusDisplay;

import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

//import android.app.Application;
import android.app.NotificationManager;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;

/**
 * @author Apocrypha
 * @see Application
 */
public class CustodianApplication {

	/**
	 * Returns the application instance
	 * 
	 * @see http://habrahabr.ru/post/27108/ Реализация Singleton в JAVA
	 * @see http://habrahabr.ru/post/129494/ Правильный Singleton в Java
	 */
	public static CustodianApplication getInstance() {
		if (instance == null)
			synchronized (CustodianApplication.class) {
				if (instance == null)
					instance = new CustodianApplication();
			}
		return instance;
	}

	/**
	 * Singleton
	 */
	private static volatile CustodianApplication instance;

	// ********************************************************
	public static Context context;

	private CustodianApplication() {
		try {
			initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Initializations calls in correct order
	 * 
	 * Implementations should be as quick as possible (for example using lazy
	 * initialization of state) since the time spent in this function directly
	 * impacts the performance of starting the first activity, service, or
	 * receiver in a process.
	 * 
	 * @throws Exception
	 * 
	 * @see android.app.Application#onCreate()
	 * @see ganga.custodian.LoggingService
	 */
	private void initialize() throws Exception {
		context = Application.context;

		preferences = new Preferences(context);

		powerManager = new CustodianPowerManager(context);
		if (preferences.stayScreenOn()) {
			powerManager.acquireScreenWakeLock();
		}

		dbHelper = new DBHelper(context);

		accelerometerMonitor = new AccelerometerMonitor(this);
		accelerometerMonitor.start();

		executor = new ScheduledThreadPoolExecutor(executorPoolSize);
		executor.scheduleAtFixedRate(accelerometerMonitor.transmitter, AccelerometerMonitor.Transmitter.InitialDelay,
				AccelerometerMonitor.Transmitter.Period, TimeUnit.SECONDS);

		locationMonitor = new LocationMonitor();
		locationMonitor.start();

		initializeDSP();
		notificator = new StatusDisplay(context);
		notificator.stopWatchOff();
		//accelerometerMonitor.stop();
	}

	private void initializeDSP() {
		// send c++ Database connection string

	}

	public void terminate() {
		locationMonitor.stop();

		if (accelerometerMonitor != null)
			accelerometerMonitor.stop();

		if (!executor.isShutdown())
			executor.shutdown();

		if (dbHelper != null)
			dbHelper.close();

		powerManager.release();
		notificator.hide();

	}

	/**
	 * If accelerometerMonitor is null - don't use it
	 */
	public static AccelerometerMonitor accelerometerMonitor;
	public String cardioMonitor;

	public ScheduledThreadPoolExecutor executor;
	private static final int executorPoolSize = 3;
	public DBHelper dbHelper;
	private static Preferences preferences;
	CustodianPowerManager powerManager;
	LocationMonitor locationMonitor;
	StatusDisplay notificator;
}
